/**
 * @description ...
 * @author cx
 * @date 2024.08.14 10:22
 */


package com.cx.living.lock;

public class DeadlockExample {
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    public static void main(String[] args) {
        DeadlockExample example = new DeadlockExample();
        example.createDeadlock();
    }

    public void createDeadlock() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock1) {
                    System.out.println("Thread 1: Holding lock 1...");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread 1: Waiting for lock 2...");
                    synchronized (lock2) {
                        System.out.println("Thread 1: Holding lock 1 & 2...");
                    }
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock2) {
                    System.out.println("Thread 2: Holding lock 2...");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread 2: Waiting for lock 1...");
                    synchronized (lock1) {
                        System.out.println("Thread 2: Holding lock 2 & 1...");
                    }
                }
            }
        });

        thread1.start();
        thread2.start();

    }
}

//分析死锁的产生过程
//        互斥条件：lock1和lock2在同一时间只能被一个线程持有。
//        占有且等待条件：thread1持有lock1并等待lock2，thread2持有lock2并等待lock1。
//        不可抢占条件：线程持有的锁不能被其他线程强制剥夺，只能由持有线程自行释放。
//        循环等待条件：thread1等待lock2，而thread2等待lock1，形成了一个循环等待的闭环。
//        在这个例子中，thread1首先持有lock1，然后等待lock2。与此同时，thread2持有lock2，然后等待lock1。由于两个线程都在等待对方的锁，并且不会释放自己已经持有的锁，因此形成了死锁。
//
//        如何避免死锁
//        避免死锁的方法主要有以下几种：
//
//        避免嵌套锁：减少持有多个锁的情况，尽量避免嵌套锁。
//        锁的顺序：按一定的顺序获取锁，确保所有线程按相同的顺序获取锁。
//        使用超时机制：使用带有超时机制的锁尝试获取锁，如果超时则放弃。
//        死锁检测和恢复：在复杂系统中，可以使用死锁检测算法，检测到死锁时采取恢复措施，如回滚或强制释放资源。
//        示例：按顺序获取锁
//        通过按顺序获取锁，可以避免死锁。例如，确保所有线程总是先获取lock1，然后再获取lock2：
//
//        java
//        复制代码

